/*
 * Funny Language - a free style programming language.
 * Copyright (C) 2015 by fanguangping (fanguangping@163.com)
 * test_statement.c
 */

#include <stdlib.h>
#include "runner_fa.h"

static void test_alloc_statement() {
	Statement *s = alloc_statement();
	assert_non_null(s);
}

static void test_init_sym() {
	Statement *s = init_sym("define");
	assert_non_null(s);
	assert_string_equal(s->symbol, "define");
	assert_true(s->type == SYM);
	assert_null(s->children);
}

static void test_init_arg() {
	Statement *s = init_arg();
	assert_non_null(s);
	assert_null(s->symbol);
	assert_true(s->type == ARG);
	assert_non_null(s->children);
}

static void test_init_loop() {
	Statement *s = init_loop();
	assert_non_null(s);
	assert_null(s->symbol);
	assert_true(s->type == LOOP);
	assert_non_null(s->children);
}

static void test_get_arg_name() {
	assert_null(get_arg_name(NULL));
	Statement *s = init_arg();
	add_statement(s, "A_ARG", SYM);
	assert_string_equal(get_arg_name(s), "A_ARG");
	add_statement(s, "TWO_ARG", SYM);
	assert_null(get_arg_name(s));
	s = init_sym("A_SYM");
	assert_null(get_arg_name(s));
}

static void test_set_arg_name() {
	set_arg_name(NULL, NULL);
	Statement *s = init_arg();
	add_statement(s, "A_ARG", SYM);
	set_arg_name(s, "TWO_ARG");
	assert_string_equal(get_arg_name(s), "TWO_ARG");
}

static void test_equal_sym() {
	Statement *s = init_sym("A_SYM");
	assert_false(equal_sym(NULL, NULL));
	assert_false(equal_sym(NULL, "A_SYM"));
	assert_false(equal_sym(s, NULL));
	assert_true(equal_sym(s, "A_SYM"));
}

static void test_equal_arg() {
	Statement *s = init_arg();
	add_statement(s, "A_ARG", SYM);
	assert_false(equal_arg(NULL, NULL));
	assert_false(equal_arg(NULL, "A_ARG"));
	assert_false(equal_arg(s, NULL));
	assert_true(equal_arg(s, "A_ARG"));
}

static void test_empty_statement() {
	Statement *s = init_arg();
	assert_true(empty_statement(NULL));
	assert_true(empty_statement(s));
	s = init_sym("");
	assert_false(empty_statement(s));
	s = init_loop();
	assert_false(empty_statement(s));
}

static void test_equal_statement() {
	Statement *a = create_statement();
	Statement *b = create_statement();
	assert_true(equal_statement(a, b));
}

static void test_to_string_statement() {
	assert_string_equal(to_string_statement(create_statement()), STATEMENT_STRING);
	assert_string_equal(to_string_statement(create_loop_statement()), LOOP_STATEMENT_STRING);
	assert_string_equal(to_string_statement(NULL), "");
}

static void test_calc_statement_prefix() {
	Statement *s = create_statement();
	assert_string_equal(calc_statement_prefix(s), "def");
	assert_null(calc_statement_prefix(NULL));
	Statement *oneArg = init_arg();
	add_statement(oneArg, "define", SYM);
	assert_string_equal(calc_statement_prefix(oneArg), "def");
}

static void test_match_statement() {
	Statement *s1 = init_sym("abc");
	Statement *s2 = init_sym("abc");
	Statement *s3 = init_sym("def");
	Statement *s4 = init_arg();
	add_statement(s4, "abc", SYM);
	Statement *s5 = init_arg();
	add_statement(s5, "abc", SYM);
	Statement *s6 = init_arg();
	add_statement(s6, "def", SYM);

	assert_false(match_statement(NULL, NULL));
	assert_false(match_statement(s1, NULL));
	assert_false(match_statement(NULL, s1));
	assert_true(match_statement(s1, s2));
	assert_false(match_statement(s1, s3));
	assert_true(match_statement(s4, s5));
	assert_true(match_statement(s4, s6));
	assert_false(match_statement(s1, s4));
}

int main(int argc, char **argv) {
	const struct CMUnitTest tests[] = {
			cmocka_unit_test(test_alloc_statement),
			cmocka_unit_test(test_init_sym),
			cmocka_unit_test(test_init_arg),
			cmocka_unit_test(test_init_loop),
			cmocka_unit_test(test_get_arg_name),
			cmocka_unit_test(test_set_arg_name),
			cmocka_unit_test(test_equal_sym),
			cmocka_unit_test(test_equal_arg),
			cmocka_unit_test(test_empty_statement),
			cmocka_unit_test(test_equal_statement),
			cmocka_unit_test(test_to_string_statement),
			cmocka_unit_test(test_calc_statement_prefix),
			cmocka_unit_test(test_match_statement),
	};
	return cmocka_run_group_tests(tests, NULL, NULL);
}
